import logging
import json
import os
from typing import List
import time
from threading import Event, Thread
from concurrent.futures import ThreadPoolExecutor, as_completed
from sqlalchemy import or_

from .task_generate_thesis import FuncGenerateThesis

from common import TaskStatus, isDevEnv, task_queue
from ExtendRegister.model_register import Thesis

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(thread)s %(threadName)s  %(filename)s : %(levelname)s  %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)


LOGGER = logging.getLogger(__name__)


class TaskExecutor(Thread):
    def __init__(self, flask_app):

        if flask_app is None:
            raise Exception("init TaskExecutor flaskApp is None")
        LOGGER.info(f"初始化TaskExecutor[{id(self)}]")

        super().__init__(name="TaskExecutor")

        self.shutdownEvent = Event()
        self.flask_app = flask_app

        # 线程池1
        self.executor = ThreadPoolExecutor(
            max_workers=5, thread_name_prefix="PooledAsyncTaskWorker"
        )

    def shutdown(self):
        LOGGER.info(
            f"TaskExecutor[{id(self)}] 开始 shutdown 。已set了 shutdownEvent,等待子线程们自行退出"
        )

        self.shutdownEvent.set()
        self.executor.shutdown(wait=False, cancel_futures=True)

        LOGGER.info(f"TaskExecutor[{id(self)}] shutdown 工作完毕")

    def loadOldTask(self):

        class LoadTask(Thread):
            def __init__(self, flaskApp):
                super().__init__()
                self.flaskApp = flaskApp

            def run(self):
                # 等主线程监听任务队列
                time.sleep(4)
                with self.flaskApp.app_context():
                    thesisList: List[Thesis] = Thesis.query.filter(
                        or_(
                            Thesis.status == TaskStatus.INIT,
                            Thesis.status == TaskStatus.RUNING,
                        )
                    ).all()
                    if len(thesisList) == 0:
                        LOGGER.info("db中未找到堆积的任务需要处理")
                        return
                    LOGGER.info(f"db中找到{len(thesisList)} 个论文正在生成，恢复任务")
                    for t in thesisList:
                        task_queue.pubGenerateThesisTask(t.id)

        LoadTask(self.flask_app).start()

    def taskLoop(self):
        while True:
            if self.shutdownEvent.is_set():
                LOGGER.info("监听线程检测到shutdone event")
                return

            task = task_queue.popTaskBlocking()

            if task is None:
                continue
            task = json.loads(task)

            LOGGER.info(f"收到任务 {task}")

            if task["type"] == task_queue.TaskType.GEN_THESIS:
                self.executor.submit(
                    FuncGenerateThesis,
                    self.flask_app,
                    task["thesisId"],
                    self.shutdownEvent,
                )
                continue

            LOGGER.info(f"任务没有处理逻辑 {task}")

    def run(self):

        # 异步，sleep，等下边的 listen 建立起来了，检查db，把老任务push到队列中
        self.loadOldTask()
        # task_executor 主线程要干的事，监听任务队列，分发给handler
        with self.flask_app.app_context():
            self.taskLoop()
